Installing Elasticsearch and Kibana with Docker Compose
It has been a month since my last note; I've been busy with exercise and fitness, feeling a bit lazy.
I've been wanting to practice with Elasticsearch recently, but I don't want to install these services directly on my local machine. As usual, I'm using Docker to build the environment. Here is a single-node configuration modified from the official Elastic GitHub Docker-Compose example.
Environment Setup
Create Data Directories
First, create the necessary data directories and set the correct permissions to prevent the service from failing to start due to permission issues.
# Create data directory
mkdir -p volumes/elasticsearch/data
# Set permissions (1000 is the user ID inside the Elasticsearch container)
sudo chown -R 1000:1000 volumesTIP
- I intentionally did not create a volume for logs, as permission issues with log files can cause startup failures when upgrading or migrating Elasticsearch.
- Kibana does not store critical data, so no data volume was created for it.
Configuration Files
Environment Variable Settings (.env)
Create a .env file to manage environment variables:
# Password for the 'elastic' user (at least 6 characters)
ELASTIC_PASSWORD=YourPassword
# Password for the 'kibana_system' user (at least 6 characters)
KIBANA_PASSWORD=Wing1205
# Version of Elastic products
STACK_VERSION=9.1.4
# Set the cluster name
CLUSTER_NAME=docker-cluster
# Set to 'basic' or 'trial' to automatically start the 30-day trial
LICENSE=basic
#LICENSE=trial
# Port to expose Elasticsearch HTTP API to the host
ES_PORT=9200
#ES_PORT=9200
# Port to expose Kibana to the host
KIBANA_PORT=5601
#KIBANA_PORT=80
# Increase or decrease based on the available host memory (in bytes)
# 1GB = 1073741824 bytes
MEM_LIMIT=2147483648Docker Compose Configuration
Create a docker-compose.yml file:
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
container_name: elasticsearch
restart: always
environment:
- node.name=elasticsearch
- cluster.name=${CLUSTER_NAME}
- discovery.type=single-node
- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=false
- xpack.security.transport.ssl.enabled=false
- xpack.license.self_generated.type=${LICENSE}
- ES_JAVA_OPTS=-Xms512m -Xmx512m -Xlog:gc:stdout:time,level,tags
volumes:
- ./volumes/elasticsearch/data:/usr/share/elasticsearch/data
ports:
- ${ES_PORT}:9200
mem_limit: ${MEM_LIMIT}
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test: ["CMD-SHELL", "curl -s -u elastic:${ELASTIC_PASSWORD} http://localhost:9200/_cluster/health | grep -q 'yellow\\|green'"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
kibana:
depends_on:
elasticsearch:
condition: service_healthy
image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
container_name: kibana
restart: always
environment:
- SERVER_NAME=kibana
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- ELASTICSEARCH_USERNAME=kibana_system
- ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
ports:
- ${KIBANA_PORT}:5601
mem_limit: ${MEM_LIMIT}
healthcheck:
test: ["CMD-SHELL", "curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'"]
interval: 30s
timeout: 10s
retries: 5
start_period: 60s
setup:
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
container_name: elasticsearch-setup
user: "0"
command: >
bash -c '
echo "Waiting for Elasticsearch to start...";
until curl -s -u elastic:${ELASTIC_PASSWORD} http://elasticsearch:9200/_cluster/health?pretty | grep -q "yellow\|green"; do
echo "Elasticsearch is not ready yet, waiting...";
sleep 10;
done;
echo "Setting password for kibana_system user...";
curl -s -X POST -u elastic:${ELASTIC_PASSWORD} -H "Content-Type: application/json" \
http://elasticsearch:9200/_security/user/kibana_system/_password \
-d "{\"password\":\"${KIBANA_PASSWORD}\"}";
echo "Initialization complete!";
'
depends_on:
elasticsearch:
condition: service_healthyConfiguration Details
Settings
- Single-node mode:
discovery.type=single-nodeis suitable for development environments. - SSL disabled: To simplify configuration, SSL for both HTTP and Transport layers has been disabled.
- Memory locking:
bootstrap.memory_lock=trueprevents the JVM heap from being swapped to disk. - Health check: Ensures that dependent services only start after the primary service is running normally.
- kibana_system password: Elasticsearch automatically creates the
kibana_systemaccount, but the password is a random string. Therefore, the setup service uses the API to set a specified password.
Common Issues and Solutions
Insufficient memory:
- Adjust
MEM_LIMITin.envor modifyES_JAVA_OPTS. - It is recommended to set the JVM Heap to about 50% of the host's memory.
- Adjust
Permission issues:
- Verify that
volumes/elasticsearch/datahas UID 1000:1000 permissions. - If errors persist, you can try
sudo chmod -R 777 volumes/elasticsearch/datafor testing (development environments only).
- Verify that
Changelog
- 2025-09-24 Initial document creation.
- 2025-11-04 Fixed missing
restartconfiguration in the YAML file, which prevented automatic startup after a reboot.
